package com.peaksport.framework.util;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TemporalType;

import org.hibernate.query.NativeQuery;
import org.hibernate.transform.Transformers;

import com.peaksport.framework.base.entity.CoreBaseEntity;
import com.peaksport.framework.exception.PKDevException;

/**
 * 
 * 这个类可以取消，已经把有关DB操作的调整到dao中实现
 * @author jinbin_guo  2019年4月30日 上午11:33:48
 *
 */
@Deprecated
public class PKDBUtils {
	

	/**
	 * create a instance of query for execute
	 * @param em
	 * @param sql
	 * @param resultClass
	 * @param isMapTransfer
	 * @return
	 */
	private static NativeQuery<?> createNativeQuery(EntityManager em, String sql, Class<?> resultClass, boolean isMapTransfer) {
		Query query = null;
		if (resultClass == null) query = em.createNativeQuery(sql);
		else if (resultClass != null && isMapTransfer) query = em.createNativeQuery(sql);
		else if (resultClass != null && !isMapTransfer) query = em.createNativeQuery(sql, resultClass);
		if (query instanceof NativeQuery) return (NativeQuery<?>)query;
		throw PKDevException.throwException("创建方言NativeQuery返回异常createNativeQuery,返回类型[%s]",query.getClass().getName());
	}
	
	
	public static Object queryOneValueForNative(EntityManager em, String sql) {
		Object obj = queryOneRecordForNative(em, sql, null);
		if (obj == null) return obj;
		if (obj instanceof Object[]) throw new PKDevException(String.format("SQL语句Select字段只能1个,sql: [%s]", sql));
		return obj;
		
	}
	
	
	public static Object queryOneRecordForNative(EntityManager em, String sql, Class<?> resultClass) {
		return queryOneRecordForNative(em, sql, resultClass,true);
	}
	
	/**
	 * 
	 * @param em
	 * @param sql
	 * @param resultClass
	 * @param isMapTransfer
	 * @return
	 */
	
	public static Object queryOneRecordForNative(EntityManager em, String sql, Class<?> resultClass, boolean isMapTransfer) {
		List<?> lstResult = queryRecordForNative(em, sql, resultClass,isMapTransfer);
		if (lstResult.isEmpty()) return null;
		else if (lstResult.size() == 1) return lstResult.get(0);
		else throw new PKDevException("执行queryOneRecordForNative超过1行数据");
	}
	
	public static List<?> queryRecordForNative(EntityManager em, String sql, Class<?> resultClass) {
		return queryRecordForNative(em, sql, resultClass,true);
		
	}
	@SuppressWarnings({ "unchecked", "deprecation" })
	public static List<?> queryRecordForNative(EntityManager em, String sql, Class<?> resultClass, boolean isMapTransfer) {
		NativeQuery<?> query = createNativeQuery(em, sql, resultClass, isMapTransfer);
		if (resultClass != null && isMapTransfer)
			query.unwrap(NativeQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
			//query.unwrap(NativeQuery<HashMap>.class).setResultTransformer(Transformers.aliasToBean(HashMap.class));
		List<?> lstResult = query.getResultList();
		if (resultClass == null || !isMapTransfer) return lstResult;
		List<Object> newLstResult = new ArrayList<Object>(lstResult.size());
		Map<String,Field> mapAllFieldForTableFiled = PKClassUtils.getAllTableField(resultClass);
		for (int i = 0, len = lstResult.size(); i < len; i++) {
			//TODO 这里暂时简单对象字段的映射,后续重新调整支持复杂对象
			Map<String, Object> record = (Map<String, Object>) lstResult.get(0);
			Object obj = PKInvokeUtils.newInstance(resultClass);
			for(Map.Entry<String,Object> entry: record.entrySet()) {
				String key = entry.getKey();
				Object value = entry.getValue();
				Field field = mapAllFieldForTableFiled.get(key);
				Class<?> fieldClass = field.getType();
				//实体类字段
				if (PKClassUtils.isAssignableFrom(CoreBaseEntity.class, fieldClass)) {
					CoreBaseEntity coreBaseEntity = (CoreBaseEntity) PKInvokeUtils.newInstance(fieldClass);
					coreBaseEntity.setId((String)value);
					value = coreBaseEntity;
				}
						
				PKInvokeUtils.setFieldValue(obj, field.getName(), value);
			}
			newLstResult.add(obj);
			
		}
		return newLstResult;
	}
	
	public static boolean queryExistsForNative(EntityManager em, String sql) {
		List<?> list = queryRecordForNative(em, sql, null);
		return !PKPublicUtils.isEmpty(list);
		
	}
	
	public static int executeSqlForNative(EntityManager em, String sql,String[] paramNames,Object[] paramValues,HashMap<String, TemporalType> dateTemporalType) {
		Query query = createNativeQuery(em, sql, null, false);
		if (paramNames == null) paramNames = new String[0];
		if (paramValues == null) paramValues = new Object[0];
		if (dateTemporalType == null) dateTemporalType = new HashMap<>(0);
		if (paramNames.length != paramValues.length) {
			throw PKDevException.throwException("执行executeSqlForNative(...)SQL脚本的参数名&参数值个数必须匹配.");
		}
		for (int i = 0, len = paramNames.length; i < len; i++) {
			String paramName = paramNames[i];
			Object paramValue = paramValues[i];
			if (paramValue instanceof Date || paramValue instanceof Calendar) {
				TemporalType temporalType = dateTemporalType.get(paramName);
				if (temporalType == null) temporalType = TemporalType.TIMESTAMP;
				if (paramValue instanceof Date)
					query.setParameter(paramName, (Date)paramValue, temporalType);
				else query.setParameter(paramName, (Calendar)paramValue, temporalType);
			} else {
				query.setParameter(paramName, paramValue);
			}
		}
		return query.executeUpdate();
	}
	
	public static int executeSqlForNative(EntityManager em, String sql) {
		return executeSqlForNative(em, sql, null, null, null);
	} 
	
	/**
	 * 批量执行SQL
	 * @param em
	 * @param sqls
	 * @return
	 */
	public static int[] batchExecuteSqlForNative(EntityManager em, String... sqls) {
		if (sqls == null) return null;
		int[] results = new int[sqls.length];
		for (int i = 0, len = sqls.length; i < len; i++) {
			results[i] = executeSqlForNative(em, sqls[i]);
		}
		return results;
	}
	
	/**
	 * 按实体保存
	 * @param em
	 * @param entity
	 * @return
	 */
	public static String saveEntity(EntityManager em, CoreBaseEntity entity) {
		em.persist(entity);
		return entity.getId();
	}	
	/**
	 * 获取当前时间(数据库)
	 * @param em
	 * @return
	 */
	public static Date getCurrentDate(EntityManager em) {
		String sql = "select sysdate from dual";
		return (Date)queryOneValueForNative(em, sql);
	}
	
	
}
